/* Copyright 2014 Jan Wolter */

#include "stack.h"
#include "uthash.h"

/* Getting much above this value starts my computer thrashing. */
#define MAXHASH 10000000

typedef struct {
    char *state;
    UT_hash_handle hh;
} Visit;

Visit *visited= NULL;

/* Check if we have ever seen the given state before.  If not, add it to the
 * visited list. The passed in state will be either freed or added to the
 * visited hash, so either way, it is consumed.
 */
int visitedState(char *state)
{
    Visit *found;

    /* This only happens if we aren't using states in this game at all */
    if (state == NULL) return 0;

    /* Check if the state is already in the hash table */
    HASH_FIND_STR(visited, state, found);
    if (found)
    {
	free(state);
	return 1;
    }

    /* Check if our hash table is too big. If so, we just give up */
    if (nVisited() > MAXHASH)
    {
	free(state);
	return -1;
    }

    /* Add it to the hash table */
    Visit *new= (Visit *)malloc(sizeof(Visit));
    new->state= state;
    HASH_ADD_KEYPTR(hh, visited, state, strlen(state), new);

    return 0;
}

/* Empty the visited table, and get it ready for a new game. */
void cleanVisited()
{
    Visit *v, *tmp;
    HASH_ITER(hh, visited, v, tmp)
    {
	HASH_DEL(visited, v);
	free(v->state);
	free(v);
    }
    visited= NULL;
}

unsigned int nVisited()
{
    return HASH_COUNT(visited);
}
